Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Displaying Raw • Download


meshchatx/src/backend/database/legacy_migrator.py 147e9451330dfa57b06aa877aa88941b226588af (147e9451) Text, 6.07 KB

Tff7b72import T7ee787os


Tff7b72class T56d364LegacyMigratorTb4b4b4:
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3providerTb4b4b4, Te6edf3reticulum_config_dirTb4b4b4, Te6edf3identity_hash_hexTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffprovider Tff7b72= Te6edf3provider
Tff7b72selfTff7b72.Td2a8ffreticulum_config_dir Tff7b72= Te6edf3reticulum_config_dir
Tff7b72selfTff7b72.Td2a8ffidentity_hash_hex Tff7b72= Te6edf3identity_hash_hex

Tff7b72def Td2a8ffget_legacy_db_pathTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Detect the path to the legacy database based on the Reticulum config directory."""
Te6edf3possible_dirs Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72if Tff7b72selfTff7b72.Td2a8ffreticulum_config_dirTb4b4b4:
Te6edf3possible_dirsTff7b72.Td2a8ffappendTb4b4b4(Tff7b72selfTff7b72.Td2a8ffreticulum_config_dirTb4b4b4)

T8b949e# Add common default locations
Te6edf3home Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexpanduserTb4b4b4(Ta5d6ff"Ta5d6ff~Ta5d6ff"Tb4b4b4)
Te6edf3possible_dirsTff7b72.Td2a8ffappendTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3homeTb4b4b4, Ta5d6ff"Ta5d6ff.reticulum-meshchatTa5d6ff"Tb4b4b4)Tb4b4b4)
Te6edf3possible_dirsTff7b72.Td2a8ffappendTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3homeTb4b4b4, Ta5d6ff"Ta5d6ff.reticulumTa5d6ff"Tb4b4b4)Tb4b4b4)

T8b949e# Check each directory
Tff7b72for Te6edf3config_dir Tff7b72in Te6edf3possible_dirsTb4b4b4:
Te6edf3legacy_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(
Te6edf3config_dirTb4b4b4,
Ta5d6ff"Ta5d6ffidentitiesTa5d6ff"Tb4b4b4,
Tff7b72selfTff7b72.Td2a8ffidentity_hash_hexTb4b4b4,
Ta5d6ff"Ta5d6ffdatabase.dbTa5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3legacy_pathTb4b4b4)Tb4b4b4:
T8b949e# Ensure it's not the same as our current DB path
T8b949e# (though this is unlikely given the different base directories)
Tff7b72tryTb4b4b4:
Te6edf3current_db_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffabspathTb4b4b4(Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8ffdb_pathTb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffabspathTb4b4b4(Te6edf3legacy_pathTb4b4b4) Tff7b72== Te6edf3current_db_pathTb4b4b4:
Tff7b72continue
Tff7b72except Tb4b4b4(Tf85149AttributeErrorTb4b4b4, Tf85149OSErrorTb4b4b4)Tb4b4b4:
T8b949e# If we can't get the absolute path, just skip this check
Tff7b72pass
Tff7b72return Te6edf3legacy_path

Tff7b72return Tff7b72None

Tff7b72def Td2a8ffshould_migrateTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Check if migration should be performed.
Only migrates if the current database is empty and a legacy database exists.
"""
Te6edf3legacy_path Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_legacy_db_pathTb4b4b4(Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3legacy_pathTb4b4b4:
Tff7b72return Tff7b72False

T8b949e# Check if current DB has any messages
Tff7b72tryTb4b4b4:
Te6edf3res Tff7b72= Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8fffetchoneTb4b4b4(Ta5d6ff"Ta5d6ffSELECT COUNT(*) as count FROM lxmf_messagesTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3res Tff7b72and Te6edf3resTb4b4b4[Ta5d6ff"Ta5d6ffcountTa5d6ff"Tb4b4b4] Tff7b72> T79c0ff0Tb4b4b4:
T8b949e# Already have data, don't auto-migrate
Tff7b72return Tff7b72False
Tff7b72except Tf85149ExceptionTb4b4b4: T8b949e# noqa: S110
T8b949e# Table doesn't exist yet, which is fine
T8b949e# We use a broad Exception here as the database might not even be initialized
Tff7b72pass

Tff7b72return Tff7b72True

Tff7b72def Td2a8ffmigrateTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Perform the migration from the legacy database."""
Te6edf3legacy_path Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_legacy_db_pathTb4b4b4(Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3legacy_pathTb4b4b4:
Tff7b72return Tff7b72False

Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffDetecting legacy database at Tffd700{Te6edf3legacy_pathTffd700}Ta5d6ff...Ta5d6ff"Tb4b4b4)

Tff7b72tryTb4b4b4:
T8b949e# Attach the legacy database
T8b949e# We use a randomized alias to avoid collisions
Te6edf3alias Tff7b72= Ta5d6fffTa5d6ff"Ta5d6fflegacy_Tffd700{Te6edf3osTff7b72.Td2a8ffurandomTb4b4b4(T79c0ff4Tb4b4b4)Tff7b72.Td2a8ffhexTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff"
Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8ffexecuteTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffATTACH DATABASE Ta5d6ff'Tffd700{Te6edf3legacy_pathTffd700}Ta5d6ff'Ta5d6ff AS Tffd700{Te6edf3aliasTffd700}Ta5d6ff"Tb4b4b4)

T8b949e# Tables that existed in the legacy Peewee version
Te6edf3tables_to_migrate Tff7b72= Tb4b4b4[
Ta5d6ff"Ta5d6ffannouncesTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffblocked_destinationsTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffconfigTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffcustom_destination_display_namesTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6fffavourite_destinationsTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6fflxmf_conversation_read_stateTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6fflxmf_messagesTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6fflxmf_user_iconsTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffspam_keywordsTa5d6ff"Tb4b4b4,
Tb4b4b4]

Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffAuto-migrating data from legacy database...Ta5d6ff"Tb4b4b4)
Tff7b72for Te6edf3table Tff7b72in Te6edf3tables_to_migrateTb4b4b4:
T8b949e# Basic validation to ensure table name is from our whitelist
Tff7b72if Te6edf3table Tff7b72not Tff7b72in Te6edf3tables_to_migrateTb4b4b4:
Tff7b72continue

Tff7b72tryTb4b4b4:
T8b949e# Check if table exists in legacy DB
T8b949e# We use a f-string here for the alias and table name, which are controlled by us
Te6edf3check_query Tff7b72= Ta5d6fffTa5d6ff"Ta5d6ffSELECT name FROM Tffd700{Te6edf3aliasTffd700}Ta5d6ff.sqlite_master WHERE type=Ta5d6ff'Ta5d6fftableTa5d6ff'Ta5d6ff AND name=?Ta5d6ff" T8b949e# noqa: S608
Te6edf3res Tff7b72= Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8fffetchoneTb4b4b4(Te6edf3check_queryTb4b4b4, Tb4b4b4(Te6edf3tableTb4b4b4,Tb4b4b4)Tb4b4b4)

Tff7b72if Te6edf3resTb4b4b4:
T8b949e# Get columns from both databases to ensure compatibility
T8b949e# These PRAGMA calls are safe as they use controlled table/alias names
Te6edf3legacy_columns Tff7b72= Tb4b4b4[
Te6edf3rowTb4b4b4[Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4]
Tff7b72for Te6edf3row Tff7b72in Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8fffetchallTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ffPRAGMA Tffd700{Te6edf3aliasTffd700}Ta5d6ff.table_info(Tffd700{Te6edf3tableTffd700}Ta5d6ff)Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Tb4b4b4]
Te6edf3current_columns Tff7b72= Tb4b4b4[
Te6edf3rowTb4b4b4[Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4]
Tff7b72for Te6edf3row Tff7b72in Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8fffetchallTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ffPRAGMA table_info(Tffd700{Te6edf3tableTffd700}Ta5d6ff)Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Tb4b4b4]

T8b949e# Find common columns
Te6edf3common_columns Tff7b72= Tb4b4b4[
Te6edf3col Tff7b72for Te6edf3col Tff7b72in Te6edf3legacy_columns Tff7b72if Te6edf3col Tff7b72in Te6edf3current_columns
Tb4b4b4]

Tff7b72if Te6edf3common_columnsTb4b4b4:
Te6edf3cols_str Tff7b72= Ta5d6ff"Ta5d6ff, Ta5d6ff"Tff7b72.Td2a8ffjoinTb4b4b4(Te6edf3common_columnsTb4b4b4)
T8b949e# We use INSERT OR IGNORE to avoid duplicates
T8b949e# The table and columns are controlled by us
Te6edf3migrate_query Tff7b72= Ta5d6fffTa5d6ff"Ta5d6ffINSERT OR IGNORE INTO Tffd700{Te6edf3tableTffd700}Ta5d6ff (Tffd700{Te6edf3cols_strTffd700}Ta5d6ff) SELECT Tffd700{Te6edf3cols_strTffd700}Ta5d6ff FROM Tffd700{Te6edf3aliasTffd700}Ta5d6ff.Tffd700{Te6edf3tableTffd700}Ta5d6ff" T8b949e# noqa: S608
Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8ffexecuteTb4b4b4(Te6edf3migrate_queryTb4b4b4)
Tffa657printTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ff - Migrated table: Tffd700{Te6edf3tableTffd700}Ta5d6ff (Tffd700{Tffa657lenTb4b4b4(Te6edf3common_columnsTb4b4b4)Tffd700}Ta5d6ff columns)Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72elseTb4b4b4:
Tffa657printTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ff - Skipping table Tffd700{Te6edf3tableTffd700}Ta5d6ff: No common columns foundTa5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff - Failed to migrate table Tffd700{Te6edf3tableTffd700}Ta5d6ff: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4)

Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8ffexecuteTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffDETACH DATABASE Tffd700{Te6edf3aliasTffd700}Ta5d6ff"Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffLegacy migration completed successfully.Ta5d6ff"Tb4b4b4)
Tff7b72return Tff7b72True
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffMigration from legacy failed: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72return Tff7b72False


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────